#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

// BIP的大小
#define BIP_LENGTH 1024
// 打印格式
#define PRINT_FORMAT "[%s@%s %s]# "
// 参数表大小
#define ARGV_SIZE 128
// cmd命令大小
#define CMD_SIZE 128

// 参数表
int g_argc = 0;
char* g_argv[ARGV_SIZE];

// 1.基本信息的三个接口
char* USER_Information()
{
    char* getuser = getenv("USER");
    return NULL == getuser ? NULL : getuser;     
}

char* HOSTNAME_Information()
{
    char* gethost = getenv("HOSTNAME");
    return NULL == gethost ? NULL : gethost;
}

char* PWD_Information()
{
    char* getpwd = getenv("PWD");
    return NULL == getpwd ? NULL : getpwd;
}

// 基本信息打印
void Base_Information_Printf()
{
    char BIP[BIP_LENGTH];
    snprintf(BIP, BIP_LENGTH, PRINT_FORMAT, USER_Information(), HOSTNAME_Information(), PWD_Information());
    printf("%s", BIP);
    fflush(stdout);
}

// 3.命令的接收
bool GetCmd(char* out, int size)
{
    // ls -a -l => "ls -a -l\n" 字符串
    char* c = fgets(out, size, stdin);
    if(NULL == c) return false;
    out[strlen(out) - 1] = 0; // 清理 \n
    if(strlen(out) == 0) return false; // 如果没有命令输入
    return true;
}

// 3.命令行解析
bool ParseCmd(char* cmd)
{
#define SEP " "
    g_argc = 0;
    // "ls -a -l" -> "ls" "-a" "-l"
    g_argv[g_argc++] = strtok(cmd, SEP);
    // strtok 将所有指令转换到g_argv中
    while((bool)(g_argv[g_argc++] = strtok(nullptr, SEP)));
    g_argc--;
    return true;
}

// 4. 执行命令
int Execute_Cmd()
{
    pid_t id = fork();
    if(id == 0)
    {
        // 子进程-> 进程替换
        execvp(g_argv[0], g_argv);
        exit(1);
    }
    // 父进程-> 进程等待
    int st = 0; // 退出码
    pid_t rid = waitpid(id, &st, 0);
    return st;
}

int main()
{
    while(1)
    {
        // 1. 基本信息打印
        Base_Information_Printf();
        // 2. 命令的接收和处理
        char Cmd[CMD_SIZE];
        if(!GetCmd(Cmd, sizeof(Cmd)))
            continue;
        ParseCmd(Cmd);
        // 3. 执行命令
        Execute_Cmd();
    }
    return 0;
}
